import { computed, defineComponent, ref, watch } from 'vue';
import {
  getCheckboxListProps,
  getEditorEmits,
  useFocusAndBlur,
  useNamespace,
  useCodeListListen,
  useAutoFocusBlur,
} from '@ibiz-template/vue3-util';
import { isNil } from 'ramda';
import './ibiz-checkbox-list.scss';
import { CodeListItem } from '@ibiz-template/runtime';
import { CheckBoxListEditorController } from '../checkbox-list-editor.controller';

export const IBizCheckboxList = defineComponent({
  name: 'IBizCheckboxList',
  props: getCheckboxListProps<CheckBoxListEditorController>(),
  emits: getEditorEmits(),
  setup(props, { emit }) {
    const ns = useNamespace('checkbox-list');

    const c = props.controller;

    const codeList = c.codeList;

    // 是否显示表单默认内容
    const showFormDefaultContent = computed(() => {
      if (
        props.controlParams &&
        props.controlParams.editmode === 'hover' &&
        !props.readonly
      ) {
        return true;
      }
      return false;
    });

    // 代码表数据
    const items = ref<readonly IData[]>([]);
    watch(
      () => props.data,
      newVal => {
        c.loadCodeList(newVal).then(_codeList => {
          items.value = _codeList;
        });
      },
      {
        immediate: true,
        deep: true,
      },
    );

    // 当前模式
    const currentMode = computed(() => {
      if (codeList && codeList.orMode) {
        return codeList.orMode.toLowerCase();
      }
      return 'str';
    });

    const fn = (data: CodeListItem[] | undefined) => {
      if (data) {
        items.value = data;
      }
    };

    useCodeListListen(c.model.appCodeListId, c.context.srfappid, fn);

    // 值分隔符
    let valueSeparator = ',';
    if (codeList && codeList.valueSeparator) {
      valueSeparator = codeList.valueSeparator;
    }

    const { useInFocusAndBlur, useInValueChange } = useAutoFocusBlur(
      props,
      emit,
    );

    // 选中数组
    const selectArray = computed({
      get() {
        if (!isNil(props.value)) {
          if (Object.is(currentMode.value, 'num') && items) {
            const selectsArray: Array<string | number> = [];
            const num: number =
              typeof props.value === 'string'
                ? parseInt(props.value, 10)
                : props.value;
            items.value.forEach((item: IData) => {
              // eslint-disable-next-line no-bitwise
              if ((num & item.value) === item.value) {
                selectsArray.push(item.value);
              }
            });
            return selectsArray;
          }
          if (Object.is(currentMode.value, 'str')) {
            const strVal = props.value! as Array<string | number> | string;
            if (strVal !== '') {
              if (codeList) {
                const selects: Array<string | number> =
                  c.model.valueType === 'SIMPLES'
                    ? (strVal as Array<string | number>)
                    : (strVal as string).split(valueSeparator);
                if (codeList.codeItemValueNumber) {
                  for (let i = 0, len = selects.length; i < len; i++) {
                    selects[i] = Number(selects[i]);
                  }
                }
                return selects;
              }
              return (strVal as string).split(',');
            }
          }
        }
        return [];
      },
      set(val: Array<string | number>) {
        let value: null | string | number | string[] | number[] = null;
        if (Object.is(currentMode.value, 'num')) {
          let temp: number = 0;
          val.forEach(item => {
            const numVal: number =
              typeof item === 'string' ? parseInt(item, 10) : item;
            // eslint-disable-next-line no-bitwise
            temp |= numVal;
          });
          if (c.model.valueType === 'SIMPLES') {
            value = [temp];
          } else if (c.model.valueType === 'SIMPLE') {
            value = temp;
          }
        } else if (Object.is(currentMode.value, 'str')) {
          const _datas: string[] = [];
          if (items.value.length > 0) {
            items.value.forEach((_item: IData) => {
              const index = val.findIndex((_key: unknown) =>
                Object.is(_item.value, _key),
              );
              if (index === -1) {
                return;
              }
              _datas.push(_item.value);
            });
            if (c.model.valueType === 'SIMPLES') {
              value = _datas;
            } else if (c.model.valueType === 'SIMPLE') {
              value = _datas.join(valueSeparator);
            }
          }
        }
        emit('change', value);
        useInValueChange();
      },
    });

    const onSelectArrayChange = (value: Array<string | number>) => {
      selectArray.value = value;
    };

    const valueText = computed(() => {
      const valueArr = Array.isArray(selectArray.value)
        ? selectArray.value
        : [selectArray.value];

      return items.value
        .filter(item => {
          let isInclude = false;
          valueArr.forEach(val => {
            // eslint-disable-next-line eqeqeq
            if (val == item.value) {
              isInclude = true;
            }
          });
          return isInclude;
        })
        .map(item => item.text)
        .join(',');
    });

    watch(
      valueText,
      (newVal, oldVal) => {
        if (newVal !== oldVal) {
          emit('infoTextChange', newVal);
        }
      },
      { immediate: true },
    );

    // 聚焦失焦事件
    const { componentRef: editorRef } = useFocusAndBlur(
      () => emit('focus'),
      () => useInFocusAndBlur(),
    );

    return {
      ns,
      items,
      selectArray,
      valueText,
      editorRef,
      onSelectArrayChange,
      showFormDefaultContent,
    };
  },
  render() {
    return (
      <div
        ref='editorRef'
        class={[
          this.ns.b(),
          this.disabled ? this.ns.m('disabled') : '',
          this.readonly ? this.ns.m('readonly') : '',
          this.ns.is('show-default', this.showFormDefaultContent),
          this.ns.is('grid-layout', !!this.controller.rowNumber),
        ]}
        style={
          this.controller.rowNumber
            ? `--ibiz-checkbox-list-group-row-number:${this.controller.rowNumber}`
            : ''
        }
      >
        {this.readonly ? (
          this.valueText
        ) : (
          <el-checkbox-group
            model-value={this.selectArray}
            onChange={this.onSelectArrayChange}
            {...this.$attrs}
          >
            {this.items.map((item, index: number) => (
              <el-checkbox
                key={index}
                label={item.value}
                disabled={this.disabled || item.disableSelect === true}
              >
                <span class={this.ns.e('text')}>{item.text}</span>
              </el-checkbox>
            ))}
          </el-checkbox-group>
        )}
      </div>
    );
  },
});
